#include "EventLoop.h"
#include "TcpConnection.h"
#include "TcpServer.h"
#include "ThreadPool.h"
#include <unistd.h>
#include <iostream>
#include <functional>

using std::cout;
using std::endl;
using std::bind;

ThreadPool *gPool = nullptr;

class MyTask
{
public:
    MyTask(const string &msg, const TcpConnectionPtr &con)
    : _msg(msg)
    , _con(con)
    {

    }
public:
    void process()
    {
        //处理从客户端接收的msg
        _msg;
        //数据在process中处理完毕之后，需要发给Reactor,也就是EventLoop类
        //此处线程池处理好数据_msg之后，需要将数据发给
        //EventLoop，而不是客户端，所以此处需要再实现
        //一个函数称为sendInLoop
        _con->sendInLoop(_msg);
        //线程池中的线程在处理好数据_msg之后，需要将数据
        //发送给EventLoop/Reactor,而Reactor可能在继续监听
        //客户端的请求，所以需要让线程池中的线程去通知
        //EventLoop去接收线程池发送过来的数据
        //那么就会涉及一个问题：线程池中的线程与Reactor线程
        //之间的通信问题？最终转换为线程之间如何进行通信？
        //解答：进程或者线程之间的通信可以使用eventfd
        //最终的难点就是：
        //1、eventfd如何使用 2、sendInLoop函数该如何实现
        //
        //执行sendInLoop函数的时候，需要知道EventLoop的存在
        //不然连接怎么将数据传递给EventLoop,也就是需要让
        //TcpConnection的对象知道EventLoop的存在
        //转换为一个类知道另外一个类的存在
    }
private:
    string _msg;
    TcpConnectionPtr _con;
};
//连接建立的事件
void onNewConnection(const TcpConnectionPtr &con)
{
    cout << con->toString() << " has connected!!!" << endl;
}

//消息达到的事件，也就是文件描述符可读
void onMessage(const TcpConnectionPtr &con)
{
    string msg = con->receive();
    cout << ">>>>recv message from client : " << msg << endl;

    MyTask task(msg, con);

    //需要线程池的对象
    gPool->addTask(bind(&MyTask::process, task));
}

//连接断开的事件
void onClose(const TcpConnectionPtr &con)
{
    cout << con->toString() << " has closed!!!" << endl;
}

void test()
{
    ThreadPool pool(4, 10);//创建线程池对象
    pool.start();//启动线程池
    gPool = &pool;

    TcpServer server("127.0.0.1", 8888);
    server.setAllCallback(std::move(onNewConnection)
                          , std::move(onMessage)
                          , std::move(onClose));
    server.start();
}

int main(int argc, char **argv)
{
    test();
    return 0;
}

